/*
 Copyright (C) 2008  Maurizio Monticelli

 This program is free software; you can redistribute it and/or modify it under the terms of the 
 GNU General Public License as published by the Free Software Foundation; either version 2 of the 
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
 Public License for more details.

 You should have received a copy of the GNU General Public License along with this program; if not, write 
 to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 
*/


package ch.justdoit.andriodrpncalc.model.command;

import java.util.Stack;

import ch.justdoit.andriodrpncalc.model.CalcNumber;
import ch.justdoit.andriodrpncalc.model.Model;


public abstract class Abstract2Command extends BaseCommand  {

	protected String mExressionMiddle = null;
	public Abstract2Command(Model _model) {
		super(_model);
		
		// TODO Auto-generated constructor stub
	}

	protected CalcNumber numA;
	protected CalcNumber numB;

	@Override
	public boolean doit() {
		boolean result = false;
		resetErrorMessage();
		if (mModel.stack.size() >= 2) {
				numA = mModel.stack.PopNumber();
				numB = mModel.stack.PopNumber();
				if (numA.isNumber() && numB.isNumber()) {
					doNumberOperation();
					result = true;
					
				} else {
					CalcNumber number = new CalcNumber(mModel);
					number.setToken(doExpressionOperation());
					mModel.stack.Put(number);
				}
		} else {
			mModel.setErrorMessage( mCommandName + " Error: Too few arguments");
		}
		return result;
	}

	@Override
	public boolean undo() {
		boolean result = true;
		mModel.stack.Pop();
		mModel.stack.Put(numB);
		mModel.stack.Put(numA);
		return result;
	}

	protected abstract void doNumberOperation();
	
	protected Stack<String> doExpressionOperation() {
		Stack<String> result = new Stack<String>();
		
		result.add(mExpression);
		
		if (numA.isExpression()) {
			result.addAll(numA.getTokens());
		} else {
			result.add(numA.toString());
		}
		
		if (mExressionMiddle != null) {
			result.add(mExressionMiddle);
		}
		
		if (numB.isExpression()) {
			result.addAll(numB.getTokens());
		} else {
			result.add(numB.toString());
		}
		if (mExpressionEnd != null) {
			result.add(mExpressionEnd);
		}
		
		return result;
	}
	
	public Stack<String> doOperatorExpressionOperation() {
		Stack<String> result = new Stack<String>();
		
		if (numA.isExpression()) {
			result.add("(");
			result.addAll(numA.getTokens());
			result.add(")");
			
		} else {
			result.addAll(numA.getTokens());
		}
		
		result.add(mExpression);
		
		if (numB.isExpression()) {
			result.add("(");
			result.addAll(numB.getTokens());
			result.add(")");
			
		} else {
			result.addAll(numB.getTokens());
		}
		return result;
	}
}
